/*-
 *  Copyright (C) 2009 Peter Baldwin   
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.peterbaldwin.client.android.sms2email;

import java.util.regex.Pattern;

import android.app.Activity;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;

// TODO: Option to share custom preset via email
public class EditPreferences extends Activity implements
		AdapterView.OnItemSelectedListener, TextWatcher {

	private static Long[] toLongArray(Object[] array) {
		Long[] result = new Long[array.length];
		for (int i = 0; i < array.length; i++) {
			String stringValue = String.valueOf(array[i]);
			result[i] = Long.valueOf(stringValue);
		}
		return result;
	}

	/**
	 * Creates a {@link Cursor} using column values stored as {@code
	 * <string-array>}s.
	 * 
	 * The values in the column named {@link BaseColumns#_ID} will be converted
	 * from {@link String} to {@link Long}.
	 * 
	 * @param resources
	 *            a reference to the {@link Resources} contain the column
	 *            values.
	 * @param columnNames
	 *            the names of the columns.
	 * @param columnIds
	 *            resource IDs for the {@code <string-array>}s containing the
	 *            column values.
	 * @return a cursor.
	 */
	private static Cursor createCursor(Resources resources,
			String[] columnNames, int[] columnIds) {
		MatrixCursor cursor = new MatrixCursor(columnNames);
		Object[][] columns = new Object[columnIds.length][];
		int length = 0;

		// Get column values from resources
		for (int columnIndex = 0; columnIndex < columnIds.length; columnIndex++) {
			String columnName = columnNames[columnIndex];

			int id = columnIds[columnIndex];
			Object[] column = resources.getStringArray(id);

			// All of the columns should be the same length, but using the
			// max value will result in an ArrayIndexOutOfBounds exception
			// when building the Cursor if they are not all the same length.
			length = Math.max(length, column.length);

			// Convert _ID to String
			if (columnName.equals(BaseColumns._ID)) {
				column = toLongArray(column);
			}

			columns[columnIndex] = column;
		}

		// Build cursor
		for (int rowIndex = 0; rowIndex < length; rowIndex++) {
			MatrixCursor.RowBuilder builder = cursor.newRow();
			for (int columnIndex = 0; columnIndex < columns.length; columnIndex++) {
				Object value = columns[columnIndex][rowIndex];
				builder.add(value);
			}
		}
		return cursor;
	}

	public static final String PREF_ID = "id";
	public static final String PREF_NUMBER = "number";
	public static final String PREF_FORMAT = "format";
	/**
	 * Use sms2email.com as the default provider
	 */
	public static final long DEFAULT_PREF_ID = 50;
	public static final String DEFAULT_PREF_NUMBER = "+44 7766 40 41 42";
	public static final String DEFAULT_PREF_FORMAT = "{email} {subject}\n\n{body}";
	

	private Spinner mSpinnerPresets;
	private EditText mEditNumber;
	private EditText mEditFormat;
	private Cursor mCursorPresets;
	private SimpleCursorAdapter mAdapterPresets;

	private SharedPreferences mPreferences;

	private boolean mProgrammaticTextChange;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit_preferences);
		mSpinnerPresets = (Spinner) findViewById(R.id.spinner_presets);
		mEditNumber = (EditText) findViewById(R.id.edit_number);
		mEditFormat = (EditText) findViewById(R.id.edit_format);

		mPreferences = PreferenceManager.getDefaultSharedPreferences(this);

		// Set this first to capture the event when the adapter is set.
		mSpinnerPresets.setOnItemSelectedListener(this);

		mEditNumber.addTextChangedListener(this);
		mEditFormat.addTextChangedListener(this);

		int layout = android.R.layout.simple_spinner_item;
		int dropdownLayout = android.R.layout.simple_spinner_dropdown_item;
		Resources resources = getResources();
		String[] columnNames = { CarrierColumns._ID, CarrierColumns.NAME,
				CarrierColumns.NUMBER, CarrierColumns.FORMAT };
		int[] columnIds = { R.array.carrier_ids, R.array.carrier_names,
				R.array.carrier_numbers, R.array.carrier_formats };
		mCursorPresets = createCursor(resources, columnNames, columnIds);
		String[] from = { CarrierColumns.NAME };
		int[] to = { android.R.id.text1 };
		mAdapterPresets = new SimpleCursorAdapter(this, layout, mCursorPresets,
				from, to);
		mAdapterPresets.setDropDownViewResource(dropdownLayout);
		mSpinnerPresets.setAdapter(mAdapterPresets);

		Long id = mPreferences.getLong(PREF_ID, DEFAULT_PREF_ID);
		boolean selected = selectId(id);
		if (!selected) {
			// Select "Custom" if the ID no longer exists.
			mSpinnerPresets.setSelection(0);
		}
		
		// If "Custom" is selected, load the field values from preferences.
		if (0 == mSpinnerPresets.getSelectedItemPosition()) {
			String number = mPreferences.getString(PREF_NUMBER,
					DEFAULT_PREF_NUMBER);
			String format = mPreferences.getString(PREF_FORMAT,
					DEFAULT_PREF_FORMAT);
			updateSettings(number, format);
		}
	};

	private boolean selectId(long id) {
		if (mCursorPresets.moveToFirst()) {
			int columnIndex = mCursorPresets.getColumnIndex(CarrierColumns._ID);
			do {
				if (id == mCursorPresets.getLong(columnIndex)) {
					int position = mCursorPresets.getPosition();
					mSpinnerPresets.setSelection(position);
					return true;
				}
			} while (mCursorPresets.moveToNext());
		}
		return false;
	}

	@Override
	public void onItemSelected(AdapterView<?> parent, View view, int position,
			long id) {
		if (position != 0) {
			mCursorPresets.moveToPosition(position);
			int columnIndexNumber = mCursorPresets
					.getColumnIndex(CarrierColumns.NUMBER);
			int columnIndexFormat = mCursorPresets
					.getColumnIndex(CarrierColumns.FORMAT);
			String number = mCursorPresets.getString(columnIndexNumber);
			String format = mCursorPresets.getString(columnIndexFormat);
			updateSettings(number, format);
		}
		savePreferences();
	}

	private void savePreferences() {
		long id = mSpinnerPresets.getSelectedItemId();
		String number = String.valueOf(mEditNumber.getText());
		String format = String.valueOf(mEditFormat.getText());
		SharedPreferences.Editor editor = mPreferences.edit();
		editor.clear();
		editor.putLong(PREF_ID, id);
		editor.putString(PREF_NUMBER, number);
		editor.putString(PREF_FORMAT, format);
		editor.commit();
	}
	
	private final String replaceLineBreaks(String format) {
		return format.replaceAll(Pattern.quote("<br>"), "\n");
	}

	private void updateSettings(String number, String format) {
		mProgrammaticTextChange = true;
		try {
			mEditNumber.setText(number);
			mEditFormat.setText(replaceLineBreaks(format));
		} finally {
			mProgrammaticTextChange = false;
		}
	}

	@Override
	public void onNothingSelected(AdapterView<?> parent) {
		// Pass
	}

	@Override
	public void afterTextChanged(Editable s) {
		// Pass

	}

	@Override
	public void beforeTextChanged(CharSequence s, int start, int count,
			int after) {
		// Pass

	}

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
		if (!mProgrammaticTextChange) {
			if (0 != mSpinnerPresets.getSelectedItemPosition()) {
				// Change the preset spinner to 'Custom'
				mSpinnerPresets.setSelection(0);

				// No need to call savePreferences() because it will be called
				// by onItemSelected().
			} else {
				savePreferences();
			}
		}
	}
}
